package com.zjw.spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * aspect for adding log
 * @author zjw
 *
 */
@Aspect
@Component
public class LogAspect {
//	private final String executionPress = "execution(* com.zjw.spring.aop.ICalculator.*(..))";
	private final String executionPress = "execution(* com.zjw.spring.aop.ICalculator.add(..))";

	/**
	 * add log before the method executed.
	 * @param joinPoint
	 */
	@Before(executionPress)
	public void beforeMethod(JoinPoint joinPoint){
		LogUtil.logBegin(getMethodName(joinPoint), joinPoint.getArgs());
	}

	@After(executionPress)
	public void afterMethod(JoinPoint joinPoint){
		LogUtil.logEnd(getMethodName(joinPoint), "after without result");
	}
	
	@AfterReturning(value=executionPress,returning="result")
	public void afterReturning(JoinPoint joinPoint,Object result){
		System.out.println("log: method[" + getMethodName(joinPoint) +"]'s result is :[" + result + "]");
	}
	
	@AfterThrowing(value=executionPress,throwing="ex")
	public void afterThrowing(JoinPoint joinPoint, ArithmeticException ex){
		System.out.println("log: method[" + getMethodName(joinPoint) + "] throws an exception[" + ex + "]");
		ex.printStackTrace();
	}
	
	@Around("execution(public int com.zjw.spring.aop.ICalculator.divide(int,int))")
	public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint){
		Object result = null;
		String methodName = getMethodName(proceedingJoinPoint);
		try {
			LogUtil.logBegin(methodName, proceedingJoinPoint.getArgs());//before

			result = proceedingJoinPoint.proceed();//target's method
			
			System.out.println("log: method[" + methodName + "]'s "
					+ "result is [" + result + "]");//afterReturning

		} catch (Throwable e) {
			System.out.println("log: method[" + methodName + "] "
					+ "occured an exception[" + e + "]");//afterThrowing
			e.printStackTrace();
		}finally{
			LogUtil.logEnd(methodName, null);//after
		}
		return result;
	}
	
	private String getMethodName(JoinPoint joinPoint){
		return joinPoint.getSignature().getName();
	}
}
